package com.sinsz.pay;

import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.sinsz.common.exception.ApiException;
import com.sinsz.pay.factory.Route;
import com.sinsz.pay.factory.support.SSLConstant;
import com.sinsz.pay.properties.PayProperties;
import com.sinsz.pay.support.AliPayConstant;
import com.sinsz.pay.support.Constant;
import org.apache.commons.lang.StringUtils;
import org.nutz.lang.Files;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;

/**
 * 配置类
 * <p>
 *     主要处理配置装载问题
 *     例如：加载支付宝或微信的支付证书
 * </p>
 * @author chenjianbo
 */
@Configuration
@EnableConfigurationProperties(value = {PayProperties.class})
@ComponentScan(value = "com.sinsz.pay")
public class PayAutoConfiguration {

    private final PayProperties properties;
    private final HttpServletRequest request;

    private static final Logger logger = LoggerFactory.getLogger(PayAutoConfiguration.class);

    @Autowired(required = false)
    public PayAutoConfiguration(PayProperties properties, HttpServletRequest request) {
        this.properties = properties;
        this.request = request;
    }

    /**
     * 加载微信支付证书
     * @return
     */
    @Bean(name = "wxSslLoader")
    public Boolean weChatSSlLoader() {
        if (properties.getWxpay() == null) {
            logger.info("微信支付参数未设置.");
            return true;
        }
        try {
            String cer = properties.getWxpay().getMchCer();
            File wxCer = new File(cer);
            if (!StringUtils.isEmpty(cer) && wxCer.exists() && wxCer.isFile()) {
                KeyStore keyStore  = KeyStore.getInstance("PKCS12");
                try (FileInputStream instream = new FileInputStream(wxCer)){
                    keyStore.load(instream, properties.getWxpay().getMchId().toCharArray());
                } finally {
                    logger.info("微信支付证书已加载.");
                }
                KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
                kmf.init(keyStore, properties.getWxpay().getMchId().toCharArray());
                TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
                    @Override
                    public X509Certificate[] getAcceptedIssuers() {
                        return new X509Certificate[] {};
                    }
                    @Override
                    public void checkClientTrusted(X509Certificate[] chain, String authType) {
                    }
                    @Override
                    public void checkServerTrusted(X509Certificate[] chain, String authType) {
                    }
                } };
                SSLContext sslContext = SSLContext.getInstance("TLSv1");
                sslContext.init(kmf.getKeyManagers(), trustAllCerts, new SecureRandom());
                //证书写入
                SSLConstant.instance().setWxSslSocketFactory(sslContext.getSocketFactory());
            }
        } catch (Exception e) {
            e.printStackTrace(System.out);
            throw new ApiException(Constant.DEFAULT_EXCEPTION_CODE, "微信支付证书加载异常.");
        }
        return true;
    }

    /**
     * 支付宝密钥加载
     * @return
     */
    @Bean(name = "aliSecretKeyLoader")
    public Boolean aliSecretKeyLoader() {
        if (properties.getAlipay() == null) {
            logger.info("支付宝支付参数未设置.");
            return true;
        }
        try {
            File privateFile = new File(properties.getAlipay().getPrivateKey());
            File publicFile = new File(properties.getAlipay().getPublicKey());
            if (privateFile.exists() && privateFile.isFile() && publicFile.exists() && publicFile.isFile()) {
                String privateKey = Files.read(privateFile);
                String publicKey = Files.read(publicFile);
                //加载支付宝支付客户端
                AlipayClient client = new DefaultAlipayClient(
                        AliPayConstant.GATEWAY,
                        properties.getAlipay().getAppid(),
                        privateKey,
                        AliPayConstant.FORMAT,
                        AliPayConstant.CHARSET,
                        publicKey,
                        AliPayConstant.SIGNTYPE
                );
                SSLConstant.instance().setAlipayClient(client);
                logger.info("支付宝支付参数已装载.");
            }
        } catch (Exception e) {
            e.printStackTrace(System.out);
            throw new ApiException(Constant.DEFAULT_EXCEPTION_CODE, "支付宝支付公私密钥加载异常.");
        }
        return true;
    }

    /**
     * 创建支付路由实例
     * @return
     */
    @Bean
    public Route route() {
        return new Route(properties, request);
    }


}
